﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using YonYou.U8.IN.Utility;

namespace YonYou.U8.IN.Framework.Async
{
    public class AsyncWorker
    {
        public delegate void WorkHandler(AsyncWorkerEventArgs e);

        private BackgroundWorker worker = new BackgroundWorker();

        private Control _Owner;

        private Form _LoaderForm;

        private EventHandler<AsyncWorkerEventArgs> _AsynWork;

        private EventHandler<AsyncWorkerEventArgs> _AsynComplete;

        private EventHandler<AsyncWorkerEventArgs> _AsynReport;

        public Form LoaderForm
        {
            get
            {
                return _LoaderForm;
            }
            set
            {
                _LoaderForm = value;
            }
        }

        public event EventHandler<AsyncWorkerEventArgs> AsynWork
        {
            add
            {
                _AsynWork = (EventHandler<AsyncWorkerEventArgs>)Delegate.Combine(_AsynWork, value);
            }
            remove
            {
                _AsynWork = (EventHandler<AsyncWorkerEventArgs>)Delegate.Remove(_AsynWork, value);
            }
        }

        public event EventHandler<AsyncWorkerEventArgs> AsynComplete
        {
            add
            {
                _AsynComplete = (EventHandler<AsyncWorkerEventArgs>)Delegate.Combine(_AsynComplete, value);
            }
            remove
            {
                _AsynComplete = (EventHandler<AsyncWorkerEventArgs>)Delegate.Remove(_AsynComplete, value);
            }
        }

        public event EventHandler<AsyncWorkerEventArgs> AsynReport
        {
            add
            {
                _AsynReport = (EventHandler<AsyncWorkerEventArgs>)Delegate.Combine(_AsynReport, value);
            }
            remove
            {
                _AsynReport = (EventHandler<AsyncWorkerEventArgs>)Delegate.Remove(_AsynReport, value);
            }
        }


        public AsyncWorker(Control owner, Form loaderForm)
        {
            if (owner == null)
            {
                throw new ArgumentNullException("owner");
            }
            if (loaderForm == null)
            {
                throw new ArgumentNullException("loaderForm");
            }
            _Owner = owner;
            _LoaderForm = loaderForm;
            worker.WorkerSupportsCancellation = true;
            worker.WorkerReportsProgress = true;
            worker.DoWork += DoWork;
            worker.RunWorkerCompleted += RunWorkerCompleted;
            worker.ProgressChanged += RunProgressChanged;
        }

        public AsyncWorker(Control owner)
        {
            if (owner == null)
            {
                throw new ArgumentNullException("owner");
            }
            _Owner = owner;
            worker.WorkerSupportsCancellation = true;
            worker.WorkerReportsProgress = true;
            worker.DoWork += DoWork;
            worker.RunWorkerCompleted += RunWorkerCompleted;
            worker.ProgressChanged += RunProgressChanged;
        }

        public void Start(object argument)
        {
            worker.RunWorkerAsync(argument);
            if (_LoaderForm != null)
            {
                _LoaderForm.ShowDialog(_Owner);
            }
        }

        public void Report(AsyncWorkerEventArgs e)
        {
            worker.ReportProgress(0, e);
        }

        public void Cancel()
        {
            worker.CancelAsync();
        }

        private void DoWork(object sender, DoWorkEventArgs e)
        {
            AsyncWorkerEventArgs asyncWorkerEventArgs = new AsyncWorkerEventArgs(e.Argument);
            asyncWorkerEventArgs.State = WorkerState.None;
            WorkHandler workHandler = OnWork;
            workHandler.BeginInvoke(asyncWorkerEventArgs, null, null);
            e.Result = asyncWorkerEventArgs;
            do
            {
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    asyncWorkerEventArgs.State = WorkerState.Canceled;
                    break;
                }
            }
            while (asyncWorkerEventArgs.State == WorkerState.None);
        }

        private void RunProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            AsyncWorkerEventArgs e2 = e.UserState as AsyncWorkerEventArgs;
            if (_AsynReport != null)
            {
                _AsynReport(this, e2);
            }
        }

        private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                AsyncWorkerEventArgs e2 = e.Result as AsyncWorkerEventArgs;
                if (_AsynComplete != null)
                {
                    _AsynComplete(this, e2);
                }
                if (_LoaderForm != null)
                {
                    _LoaderForm.Close();
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("[实施导航]-[AsyncWorker->RunWorkerCompleted]-[StackTrace:{0}]-[Message:{1}]", ex.StackTrace, ex.Message);
            }
        }

        protected virtual void OnWork(AsyncWorkerEventArgs e)
        {
            try
            {
                if (_AsynWork != null)
                {
                    _AsynWork(this, e);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("[实施导航]-[AsyncWorker->OnWork]-[StackTrace:{0}]-[Message:{1}]", ex.StackTrace, ex.Message);
            }
        }
    }
}
